package com.alcatel_lucent.osp.utils;


import jline.Terminal;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.TransformerUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collection;

import static org.fusesource.jansi.Ansi.Color.*;
import static org.fusesource.jansi.Ansi.ansi;

/**
 * User: guoshunw
 * Date: 13-8-19
 * Time: 下午1:51
 */
public class StringUtil {

    public static final int LEFT_PAD = 1;
    public static final int RIGHT_PAD = 2;
    public static final int LEFT_RIGHT_PAD = 3;

    private static Logger log = LoggerFactory.getLogger(StringUtil.class);

    public void clearScreen() {
        Ansi ansi = Ansi.ansi();
        System.out.print(ansi.eraseScreen().cursor(1, 1));
    }

    public void ansiPrint() {
        AnsiConsole.systemInstall();
        PrintWriter out = new PrintWriter(System.out, true);

        Ansi ansi = Ansi.ansi();

        String msg = "这是测试" + ansi.fg(RED).bg(BLUE).a("Hello").fg(GREEN).a(" World").reset();
//        String msg ="This is my test";
        clearScreen();
//        out.println(ansi.cursor(10, 63) + msg);
        out.println(msg);
        AnsiConsole.systemUninstall();
    }

    public void printMenuOnConsole(Collection<String> strMenuItems, Boolean isCenter) {
        AnsiConsole.systemInstall();

        if (null == strMenuItems || strMenuItems.isEmpty()) return;
        if (isCenter != null) isCenter = true;

        PrintWriter out = new PrintWriter(System.out, true);
        Terminal terminal = Terminal.getTerminal();
        log.info("Terminal width ={}, height ={}", terminal.getTerminalWidth(), terminal.getTerminalHeight());
        int startX = (terminal.getTerminalHeight() - (strMenuItems.size() + 2)) / 2;
        if (startX < 0 || !isCenter) startX = 0;
        Collection<Integer> menuWidths = CollectionUtils.collect(strMenuItems, TransformerUtils.invokerTransformer("length"));
        int maxMenuWidth = NumberUtils.max(ArrayUtils.toPrimitive(menuWidths.toArray(new Integer[0])));
        int menuItemIndent = 5;
        int menuWidth = maxMenuWidth + 2 * menuItemIndent;

        int startY = (terminal.getTerminalWidth() - maxMenuWidth) / 2;
        if (startY < 0 || !isCenter) startX = 0;
        Ansi ansi = Ansi.ansi();

        log.info("startX ={}, startY ={}", startX, startY);

        clearScreen();
        out.println(ansi.cursor(startX++, startY).a(StringUtils.repeat('=', menuWidth)));
        for (String strMenuItem : strMenuItems) {
            out.println(ansi().cursor(startX++, startY + menuItemIndent).a(strMenuItem));
        }
        out.println(ansi.cursor(startX++, startY).a(StringUtils.repeat('=', menuWidth)));
        out.print(ansi.cursor(startX++, startY + menuItemIndent / 2).a("Please choose: "));
        out.flush();
        AnsiConsole.systemUninstall();
    }

    public static void main(String... args) throws Exception {
//        new StringUtil().ansiPrint();
        new StringUtil().printMenuOnConsole(Arrays.asList("Test menu item1",
                "Test menu item2",
                "Test menu item3 longer",
                "Test menu4"
        ), true);
    }

    public String center(String str, int size, char padChar) {
        return pad(str, size, padChar, LEFT_RIGHT_PAD);
    }

    public String leftPad(String str, int size, char padChar) {
        return pad(str, size, padChar, LEFT_PAD);
    }

    public String rightPad(String str, int size, char padChar) {
        return pad(str, size, padChar, RIGHT_PAD);
    }

    public String pad(String str, int size, char padChar, int type) {
        int strWidth = getStringWidth(str);
        int pads = size - strWidth;
        if (pads <= 0) return str;
        if (type == LEFT_PAD) return StringUtils.repeat(padChar, pads) + str;
        if (type == RIGHT_PAD) return str + StringUtils.repeat(padChar, pads);
        //center
        str = leftPad(str, strWidth + pads / 2, padChar);
        str = rightPad(str, size, padChar);
        return str;
    }

    private int getStringWidth(String str) {
        try {
            return str.getBytes("GBK").length;
        } catch (UnsupportedEncodingException e) {
            return -1;
        }
    }
}
